package net.xyuu;

import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Calendar;
import java.util.Date;

import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class X509v3CertificateGenerator {

	public static void main(String[] args) {
		Date now = new Date();

		Calendar cal = Calendar.getInstance();
		cal.set(2099, 11, 31);
		Date end = cal.getTime();

		X509v3CertificateGenerator gen = new X509v3CertificateGenerator();
		// "CN=公司名称, E=E-MAIL地址, O=组织名称, OU=组织单位, C=国家, ST=省份(州), P=县城"
		String dn = "E=xyuu@xyuu.net,C=CN,L=WuHan,ST=BeiJing,O=www.xyuu.net,OU=XYUUStudio,CN=XYUU";
		gen.generate(dn, now, end);
		gen.save("D:/Code/workspace/platform/src/test/resources/zcms.cer");
		gen.savePublic("D:/Code/workspace/platform/src/test/resources/pub.key");
		gen.savePrivate("D:/Code/workspace/platform/src/test/resources/priv.key");

		logger.info(gen.getBase64CertString());
	}

	private static final Logger logger = LoggerFactory.getLogger(X509v3CertificateGenerator.class);

	private static final Provider PROVIDER = new BouncyCastleProvider();

	private PublicKey publickey;
	private PrivateKey privatekey;
	private byte[] cert;

	public void generate(String fqdn, Date start, Date end) {
		try {
			KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
			SecureRandom random = new SecureRandom();
			random.setSeed("8ww7a4b".getBytes());
			keygen.initialize(512, random);
			KeyPair keys = keygen.genKeyPair();
			publickey = keys.getPublic();
			privatekey = keys.getPrivate();
			X500Name owner = new X500Name(fqdn);
			X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(owner, new BigInteger(64, random), start,
					end, owner, publickey);
			ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSAEncryption").build(privatekey);
			X509CertificateHolder certHolder = builder.build(signer);
			X509Certificate certificate = new JcaX509CertificateConverter().setProvider(PROVIDER)
					.getCertificate(certHolder);
			certificate.verify(publickey);
			cert = certificate.getEncoded();
		} catch (Exception e) {
			logger.warn("证书生成出错", e);
		}
	}

	public String getBase64CertString() {
		return Base64.getEncoder().encodeToString(cert);
	}

	public void save(String filename) {
		save(cert, filename);
	}

	public void savePublic(String pubkey) {
		save(publickey.getEncoded(), pubkey);
	}

	public void savePrivate(String privkey) {
		save(privatekey.getEncoded(), privkey);
	}

	private void save(byte[] bs, String name) {
		try (FileOutputStream fos = new FileOutputStream(name)) {
			fos.write(bs);
			fos.flush();
		} catch (IOException e) {
			logger.warn("写入文件出错{}", name, e);
		}
	}
}
